﻿//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;

namespace Microsoft.Ted.Wacel.TableStorage
{
    public class TableStorageLockProvider: Base.ILockProvider
    {
        CloudTableStorage<TableItem<long>> mSubTable;
        CloudSyncRoot mSyncRoot;

        public TableStorageLockProvider(string connectionString, string name)
        {
            mSubTable = new CloudTableStorage<TableItem<long>>("Key", "Key", connectionString, name+"sub", false);
            mSyncRoot = new CloudSyncRoot(connectionString, name);
        }
        public void PutInSub(string key, long value)
        {
            mSubTable.InsertOrReplace(new TableItem<long> { Key = key, Value = value });
        }
        public long Increment(string key, long increment, long defaultValue)
        {
            string lease = mSyncRoot.Accquire(key, TimeSpan.FromSeconds(30));
            var item = mSubTable.Read(key, partitionId: key);
            long ret;
            if (item == null)
            {
                mSubTable.Insert(new TableItem<long> { Key = key, Value = defaultValue });
                ret = defaultValue;
            }
            else
            {
                ret = (long)item.Value + increment;
                mSubTable.InsertOrReplace(new TableItem<long> { Key = key, Value = ret });
            }
            mSyncRoot.Release(key, lease);
            return ret;
        }
        public long ReadAndLock(string key, long defaultValue, TimeSpan timespan, out object lockHandle)
        {
            string lease = mSyncRoot.Accquire(key, TimeSpan.FromSeconds(30));
            var item = mSubTable.Read(key, partitionId: key);
            long ret;
            if (item == null)
            {
                mSubTable.Insert(new TableItem<long> { Key = key, Value = defaultValue });
                ret = defaultValue;
            }
            else
                ret = (long)item.Value;
            lockHandle = lease;
            return ret;
        }
        public void PutAndUnlock(string key, long value, object lockHandle)
        {
            mSubTable.Replace(new TableItem<long> { Key = key, Value = value });
            mSyncRoot.Release(key, lockHandle.ToString());
        }
        public void Unlock(string key, object lockHandle)
        {
            mSyncRoot.Release(key, lockHandle.ToString());
        }
        public void Clear()
        {
            mSubTable.Clear();
        }
    }
}
